package cn.tedu.blog.server.service.impl;

import cn.tedu.blog.server.exception.ServiceException;
import cn.tedu.blog.server.mapper.*;
import cn.tedu.blog.server.pojo.dto.*;
import cn.tedu.blog.server.pojo.entity.Article;
import cn.tedu.blog.server.pojo.entity.Category;
import cn.tedu.blog.server.pojo.entity.MessagePush;
import cn.tedu.blog.server.pojo.entity.UserInfo;
import cn.tedu.blog.server.pojo.vo.*;
import cn.tedu.blog.server.repo.IArticleRepository;
import cn.tedu.blog.server.security.LoginPrincipal;
import cn.tedu.blog.server.service.IArticleService;
import cn.tedu.blog.server.utils.JsonPage;
import cn.tedu.blog.server.utils.OssUtils;
import cn.tedu.blog.server.utils.ServiceCode;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;


import java.time.LocalDateTime;
import java.util.List;

import static cn.tedu.blog.server.repo.IArticleRepository.*;

@Slf4j
@Service
public class ArticleServiceImpl implements IArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private ArticleTagMapper articleTagMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private MessagePushMapper messagePushMapper;
    @Autowired
    private IArticleRepository articleRepository;
    @Autowired
    private CommentMapper commentMapper;
    @Override
    public void addNew(ArticleAddNewDTO addNewDTO) {

        Long userId=getUserId();

        log.debug("即将执行articleService的逻辑：{}",addNewDTO);

        if(articleMapper.getByTitle(addNewDTO.getTitle())!=null){
            String message = "添加文章失败，文章"+addNewDTO.getTitle()+"已存在";
           throw  new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }
        Article article = new Article();
        BeanUtils.copyProperties(addNewDTO,article);
        LocalDateTime createTime = LocalDateTime.now();
        article.setGmtCreate(createTime);
        article.setGmtCreatePush(createTime);
        article.setGmtModified(createTime);
        article.setSort(0);
        article.setViewCount(0L);
        article.setPraiseCount(0L);
        article.setFavorCount(0L);
        article.setCommentCount(0L);
        article.setUserId(userId);
        article.setIsRecommended(0);

        Long categoryId = categoryMapper.selectIdByName(addNewDTO.getCategory());
        article.setCategoryId(categoryId);
        log.debug("插入前查询咧白哦数据：{}",article);
        int rows = articleMapper.insert(article);
        if(rows!=1){
            String message ="添文章失败，系统繁忙，错误码【1】，请稍后再试";
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }
        CategoryAddDTO categoryAddDTO = new CategoryAddDTO();
        categoryAddDTO.setId(categoryId);
        categoryAddDTO.setArticleCount(1L);
        rows = categoryMapper.updateById(categoryAddDTO);
        if(rows<1){
            String message ="修改文章分类数量关联失败，系统繁忙，错误码【2】，请稍后再试";
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }
        List<Long> tagIds=tagMapper.selectIdByName(addNewDTO.getTags());
        rows=articleTagMapper.insert(article.getId(),tagIds,createTime);
        if(rows<1){
            String message ="添文章标签关联失败，系统繁忙，错误码【3】，请稍后再试";
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }


    }


    // 审核文章
    @Override
    public void createExamineStatus(ArticleExamineNewDTO articleExamineNewDTO) {
        // 判断前端传入的审核指令是否合理
        if (articleExamineNewDTO.getExamineStatus()<2 && articleExamineNewDTO.getExamineStatus()>3){
            String message = "服务器忙, 请稍后再试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }


        // 参数补全
        Article article = new Article();
        article.setId(articleExamineNewDTO.getArticleId());
        article.setExamineStatus(articleExamineNewDTO.getExamineStatus());

        // 修改
        if (articleMapper.updateById(article)<=0){
            String message = "服务器忙, 请稍后再试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }

        // 审核时间
        articleExamineNewDTO.setExamineTime(LocalDateTime.now());
        // 创建审核记录日志
        if (articleMapper.createExamineStatus(articleExamineNewDTO)<=0){
            String message = "服务器忙, 请稍后再试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }

        String title = articleMapper.getById(articleExamineNewDTO.getArticleId()).getTitle();

        MessagePush messagePush = new MessagePush();
        messagePush.setUserId(articleExamineNewDTO.getUserId());
        messagePush.setArticleId(articleExamineNewDTO.getArticleId());
        messagePush.setTitle("【"+title+"】，审核通知");
        messagePush.setContent(articleExamineNewDTO.getMessage());
        messagePush.setGmtCreate(LocalDateTime.now());
        messagePushMapper.createMessage(messagePush);

    }


    @Override
    public int selectCount( ArticleAdminDetailVO articleAdminDetailVO) {
        int count = articleMapper.selectCount(articleAdminDetailVO);
        return count;
    }

    @Override
    public void deleteById(long id) {
        log.debug("开始处理删除文章业务, 接收到的参数id={}", id);
        // 先查询文章是否存在, 如果不存在, 则抛出异常
        ArticleDetailVO articleDetailVO = articleMapper.getById(id);
        if (articleDetailVO == null) {
            String message = "删除文章失败,尝试删除的数据(id= " + id + ")不存在! ";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }
        String url =articleDetailVO.getViewPicture();
        OssUtils.delete(url);
        // 代码走到这里说明文章存在, 则执行删除
        int rows = articleMapper.deleteById(id);
        CategoryAddDTO categoryAddDTO = new CategoryAddDTO();
        categoryAddDTO.setId(articleDetailVO.getCategoryId());
        categoryAddDTO.setArticleCount(-1L);
        rows = categoryMapper.updateById(categoryAddDTO);
        if(rows<1){
            String message ="修改文章分类数量关联失败，系统繁忙，错误码【2】，请稍后再试";
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }
        // 如果执行删除返回的受影响行数不等于1, 则抛出异常
        if (rows != 1) {
            String message = "删除文章失败,服务器忙,请稍后再试!";
            log.error(message);
            throw new ServiceException(ServiceCode.ERR_UNKNOWN, message);
        }
    }
    @Override
    public int  deleteByIds(Long [] ids) {
        List<ArticleDetailVO> list =articleMapper.selectByIds(ids);
        for (ArticleDetailVO articleDetailVO:list) {
           String url =articleDetailVO.getViewPicture();
            OssUtils.delete(url);

            CategoryAddDTO categoryAddDTO = new CategoryAddDTO();
            categoryAddDTO.setId(articleDetailVO.getCategoryId());
            categoryAddDTO.setArticleCount(-1L);
           int rows = categoryMapper.updateById(categoryAddDTO);
            if(rows<1){
                String message ="修改文章分类数量关联失败，系统繁忙，错误码【1】，请稍后再试";
                throw new ServiceException(ServiceCode.ERR_INSERT,message);
            }
        }
        log.debug("开始处理根据多个id批量删除文章业务, 接收到的参数id={}", ids);
        int rows = articleMapper.deleteByIds(ids);

        return rows;
    }

    @Override
    public void update(long id, ArticleEditDTO articleEditDTO) {
        log.debug("开始处理根据id修改文章的业务, 接收到的参数:{}", articleEditDTO);
        // 先查文章是否存在, 不存在抛出异常
        ArticleDetailVO articleDetailVO = articleMapper.getById(id);
        if (articleDetailVO == null) {
            String message = "修改文章失败, 尝试修改的文章(id= " + id + ")不存在!";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        // 代码走到这里说明文章存在
        Article article = new Article();
        BeanUtils.copyProperties(articleEditDTO, article);

        article.setId(id);
        LocalDateTime modified = LocalDateTime.now();
        article.setGmtModified(modified);
        log.debug("article:{}", article);
        int rows = articleMapper.updateById(article);
        // 如果返回的受影响行数不等于1, 抛出异常
        if (rows != 1) {
            String message = "修改文章数据失败, 服务器忙, 请稍后再试";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }
    
    @Override
    public ArticleDetailVO adminSelect(Long id) {
        log.debug("===正在执行查询ArticleService后台文章列表查询====");
        ArticleDetailVO articleDetailVO =articleMapper.adminSelect(id);
        log.debug("查询列表结果为：{}",articleDetailVO.toString());
        return articleDetailVO;
    }
    @Override
    public List<ArticleAdminDetailVO> adminSelectFindAll(ArticleAdminDetailVO articleAdminDetailVO) {
        log.debug("===正在执行查询ArticleService后台文章列表查询===={},{}",articleAdminDetailVO.toString());
        List<ArticleAdminDetailVO> list =articleMapper.adminSelectFindAll(articleAdminDetailVO);
        log.debug("分页查询所有文章列表{}",list);
        return list;
    }

    /*  ------前台部分---------   */
    @Override
    public JsonPage<ApiArticleListItemVO> listArticlesByCategoryId(Long categoryId, PageDTO pageDTO) {
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getSize());
        List<ApiArticleListItemVO> apiArticleListItemVOs = articleMapper.listArticlesByCategoryId(categoryId);
        log.debug("查寻的数据结果：{}",apiArticleListItemVOs);
        return JsonPage.restPage(new PageInfo<>(apiArticleListItemVOs));
    }

    /**
     * 最新文章查询
     * @return
     */
    @Override
    public List<ArticleStandardVO> selectNewestArticle() {
        log.debug("====执行service查询方法====");
        boolean isExpired= articleRepository.isExpired(KEY_NEWEST_ARTICLE_LIST);
        if(isExpired){
            log.debug("====执行数据库查询存入redis====");
            List<ArticleStandardVO> list =articleMapper.selectNewest();
            if(list==null){
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"数据库中没有文章");
            }
            articleRepository.putList(list,KEY_NEWEST_ARTICLE_LIST);
        }
        List<ArticleStandardVO> articleStandardVOS =articleRepository.getList(KEY_NEWEST_ARTICLE_LIST);

        return articleStandardVOS;
    }

    /**
     * 热门文章查询
     * @return
     */
    @Override
    public List<ArticleStandardVO> selectPopularArticle() {
        boolean isExpired= articleRepository.isExpired(KEY_POPULAR_ARTICLE_LIST);
        if(isExpired){
            log.debug("====执行数据库查询存入redis====");
            List<ArticleStandardVO> list =articleMapper.selectPopularArticle();
            if(list==null){
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"数据库中没有文章");
            }
            articleRepository.putList(list,KEY_POPULAR_ARTICLE_LIST);
        }
        List<ArticleStandardVO> articleStandardVOS = articleRepository.getList(KEY_POPULAR_ARTICLE_LIST);

        return articleStandardVOS;


    }

    /**
     * 管理员推荐文章查询
     * @return
     */
    @Override
    public List<ArticleStandardVO> selectIsRecommendArticle() {
        boolean isExpired= articleRepository.isExpired(KEY_IS_RECOMMEND_ARTICLE_LIST);
        if(isExpired){
            log.debug("====执行数据库查询存入redis====");
            List<ArticleStandardVO> list =articleMapper.selectIsRecommendArticle();
            if(list==null){
                throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"数据库中没有文章");
            }
            articleRepository.putList(list,KEY_IS_RECOMMEND_ARTICLE_LIST);
        }
        List<ArticleStandardVO> articleStandardVOS = articleRepository.getList(KEY_IS_RECOMMEND_ARTICLE_LIST);

        return articleStandardVOS;

    }

    /*分页查询文章列表*/
    @Override
    public JsonPage<ArticleStandardVO> selectArticleLists(Integer pageNum, Integer pageSize){
        PageHelper.startPage(pageNum,pageSize);
        log.debug("====执行数据库查询====");
        List<ArticleStandardVO> list =articleMapper.selectIsArticlePageList();
        for (ArticleStandardVO articleStandardVO : list) {
            // todo
            Long articleId = articleStandardVO.getId();
            // 通过id查询评论数量
            int commentCount = commentMapper.countByArticleId(articleId);
            articleStandardVO.setCommentCount(commentCount);
        }
        if(list==null){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"数据库中没有文章");
        }
        return JsonPage.restPage(new PageInfo<>(list));
    }


    /*查询文章数量*/
    @Override
    public Long selectArticleCount() {
        Long count =articleMapper.selectArticleCount();
        return count;
    }

    /*查询文章页面数量*/
    @Override
    public JsonPage<ArticleStandardVO> getArticleByPage(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<ArticleStandardVO> list=articleMapper.findAllList();
        return JsonPage.restPage(new PageInfo<>(list));
    }
    @Override
    public Long articleCount() {
        log.debug("开始处理查询发布文章数");
        return articleMapper.articleCount();
    }

    /**
     * 获取个人文章数据
     * @return
     */
    @Override
    public List<ArticlePersonalDetailVO> saveArticlePersonalDetail(int pagSize, int auditStatus){
        log.info("查询用户文章列表");
        // 从上下文中获得用户id
        Long userId = getUserId();
        List<ArticlePersonalDetailVO> list = articleMapper.articlePersonalDetailByUserId(userId, pagSize, auditStatus);
        // 循环遍历用户文章id,并根据文章id查询标签
        if (list != null){
            for (ArticlePersonalDetailVO articlePersonalDetailVO : list){
                // 根据文章id查询标签名称(夺表联查)
                List<String> tagNames = articleTagMapper.articleTagByArticleId(articlePersonalDetailVO.getId());
                // 将查询到的标签列表赋值给articlePersonalDetailVO
                articlePersonalDetailVO.setTags(tagNames);
            }
        }
        // 返回给控制层数据
        log.info("返回给控制层数据:{}", list);
        return list;
    }

    @Override
    public void updatePrasieById(PrasieNewDTO prasieNewDTO) {

        // 修改文章表中的点赞数
        articleMapper.updatePrasieById(prasieNewDTO.getArticleId(),prasieNewDTO.getCount());

    }
    @Override
    public int countArticleByUserId(int auditStatus) {
        log.info("查询用户发表的文章数");
        // 从上下文中获得用户id
        Long userId = getUserId();
        int articleSize = articleMapper.countArticleByUserId(userId, auditStatus);
        return articleSize;
    }

    @Override
    public List<FavoriteArticleVO> getCollectionArticle(int pagSize) {
        log.info("查询用户收藏文章列表");
        // 从上下文中获得用户id
        Long userId = getUserId();
        List<FavoriteArticleVO> list = articleMapper.collectionArticleByUserId(userId, pagSize);
        // 循环遍历用户文章id,并根据文章id查询标签
        if (list != null){
            for (FavoriteArticleVO favoriteArticleVO : list){
                // 根据文章id查询标签名称(夺表联查)
                List<String> tagNames = articleTagMapper.articleTagByArticleId(favoriteArticleVO.getId());
                // 将查询到的标签列表赋值给articlePersonalDetailVO
                favoriteArticleVO.setTags(tagNames);
            }
        }
        // 返回给控制层数据
        log.info("返回给控制层数据:{}", list);
        return list;
    }




    /*根据分类id查询文章数量*/
    @Override
    public Long countArticleByCategoryId(Long categoryId) {
      Long count =  articleMapper.countArticleByCategoryId(categoryId);

      log.error("分类文章数：{}",count);

        return count;
    }

    @Override
    public JsonPage<ApiArticleListItemVO> listArticlesByTagId(Long tagId, PageDTO pageDTO) {

        log.error("获取到的标签参数id"+tagId);
        PageHelper.startPage(pageDTO.getPageNum(),pageDTO.getSize());

        List<ApiArticleListItemVO> list = articleMapper.listArticlesByTagId(tagId);
        log.debug("====执行数据库查询===={}",list.toString());
        if(list==null){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"数据库中没有标签对应文章");
        }
        return JsonPage.restPage(new PageInfo<>(list));

    }

    @Override
    public Long countArticleBytagId(Long tagId) {
        Long count =articleMapper.countArticleBytagId(tagId);
        log.error("标签文章数：{}",count);
        return count;
    }


    /*查询文章浏览量*/
    @Override
    public int selectViewCount(Long id) {
      int count =  articleMapper.updateViewCount(id);

        return count;
    }




    /*获取用户信息*/
    public LoginPrincipal getUserInfo(){

        UsernamePasswordAuthenticationToken authenticationToken=
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext()
                        .getAuthentication();
        if(authenticationToken==null){
            throw new ServiceException(ServiceCode.ERR_UNKNOWN,"没有登录信息");
        }
        // 如果authenticationToken不为空,获得其中的用户信息
        LoginPrincipal userInfo=(LoginPrincipal) authenticationToken.getPrincipal();
        // 返回登录用户信息
        return  userInfo;
    }
    /*获取用户id*/
    public Long getUserId(){
        return getUserInfo().getId();
    }
}
